package org.luxor.common.netty.config.properties;

import org.luxor.common.netty.config.option.AuthOption;
import org.luxor.common.netty.config.option.SslOption;
import org.luxor.commons.core.utils.UuidUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

/**
 * 客户端配置
 *
 * @author Mr.yan @date 2023/8/22
 */
@ConfigurationProperties(prefix = NettyClientProperties.PREFIX)
public class NettyClientProperties {
    public static final String PREFIX = "spring.netty.client";

    private static final Boolean DEFAULT_ENABLED = Boolean.FALSE;
    private static final String DEF_HOST = "127.0.0.1";
    private static final int DEF_PORT = 8080;
    private static final Boolean DEFAULT_START_TLS = Boolean.FALSE;
    private static final SslOption DEFAULT_SSL_OPTION = new SslOption("classpath:client.crt", "classpath:client.key", null, "classpath:ca.crt");
    private static final Boolean DEF_IS_DEBUG = Boolean.TRUE;
    private static final int DEF_CONNECT_TIMEOUT_SECONDS = 10;
    private static final Boolean DEF_RECONNECT = Boolean.TRUE;
    private static final int DEF_RECONNECTION_NUM_MAX = 12;
    private static final int DEF_KEEP_ALIVE_TIME_SECONDS = 60;
    private static final int KEEP_ALIVE_TIME_SECONDS_MIN = 3;
    private static final int DEF_PACKET_SIZE_MAX = 2048;
    private static final int DEF_RESEND_MAX = 12;
    private static final int DEF_SOCKET_TIMEOUT_SECONDS = 15;


    /**
     * 启用?
     */
    private boolean enabled;

    /**
     * 客户端ID
     */
    private String id;

    /**
     * 地址
     */
    private String host;

    /**
     * 端口号
     */
    private int port;

    /**
     * 启用SSL?
     */
    private boolean startTls;

    /**
     * SSL选项参数
     */
    @NestedConfigurationProperty
    private SslOption ssl;

    /**
     * 身份认证信息
     */
    @NestedConfigurationProperty
    private AuthOption auth;

    /**
     * 启用日志?
     */
    private Boolean debug;

    /**
     * 连接超时时间(单位:秒)
     */
    private int connectTimeoutSeconds;

    /**
     * 启用自动重连
     */
    private boolean reconnect;

    /**
     * 最大重连次数
     */
    private int reconnectCountMax;

    /**
     * 保持连接超时时间(单位:秒)
     */
    private int keepAliveTimeSeconds;

    /**
     * 最大数据包大小(单位:字节)
     */
    private int packetSizeMax;

    /**
     * 接收最大数值
     */
    private int receiveQueueLimit;

    /**
     * 最大重发次数
     */
    private int resendMax;

    /**
     * 读写超时时间(单位:秒)
     */
    private int socketTimeoutSeconds;

    public NettyClientProperties() {
        this(UuidUtils.uuid(), DEF_HOST, DEF_PORT, DEF_RECONNECT, DEF_RECONNECTION_NUM_MAX);
    }

    public NettyClientProperties(String host, int port) {
        this(UuidUtils.uuid(), host, port, DEF_RECONNECT, DEF_RECONNECTION_NUM_MAX);
    }

    public NettyClientProperties(String id, String host, int port) {
        this(id, host, port, DEF_RECONNECT, DEF_RECONNECTION_NUM_MAX);
    }

    public NettyClientProperties(String id, String host, int port, boolean reconnect) {
        this(id, host, port, reconnect, DEF_RECONNECTION_NUM_MAX);
    }

    public NettyClientProperties(String id, String host, int port, boolean reconnect, int reconnectCountMax) {
        this.enabled = DEFAULT_ENABLED;
        this.id = id;
        this.port = port;
        this.host = host;
        this.startTls = DEFAULT_START_TLS;
        this.ssl = DEFAULT_SSL_OPTION;
        this.reconnect = reconnect;
        this.reconnectCountMax = reconnectCountMax;
        this.debug = DEF_IS_DEBUG;
        this.connectTimeoutSeconds = DEF_CONNECT_TIMEOUT_SECONDS;
        this.keepAliveTimeSeconds = DEF_KEEP_ALIVE_TIME_SECONDS;
        this.packetSizeMax = DEF_PACKET_SIZE_MAX;
        this.resendMax = DEF_RESEND_MAX;
        this.socketTimeoutSeconds = DEF_SOCKET_TIMEOUT_SECONDS;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public boolean isStartTls() {
        return startTls;
    }

    public void setStartTls(boolean startTls) {
        this.startTls = startTls;
    }

    public SslOption getSsl() {
        return ssl;
    }

    public void setSsl(SslOption ssl) {
        this.ssl = ssl;
    }

    public AuthOption getAuth() {
        return auth;
    }

    public void setAuth(AuthOption auth) {
        this.auth = auth;
    }

    public Boolean isDebug() {
        return debug;
    }

    public void setDebug(Boolean debug) {
        this.debug = debug;
    }

    public int getConnectTimeoutSeconds() {
        return connectTimeoutSeconds;
    }

    public void setConnectTimeoutSeconds(int connectTimeoutSeconds) {
        this.connectTimeoutSeconds = connectTimeoutSeconds;
    }

    public boolean isReconnect() {
        return reconnect;
    }

    public void setReconnect(boolean reconnect) {
        this.reconnect = reconnect;
    }

    public int getReconnectCountMax() {
        return reconnectCountMax;
    }

    public void setReconnectCountMax(int reconnectCountMax) {
        this.reconnectCountMax = reconnectCountMax;
    }

    public int getKeepAliveTimeSeconds() {
        return keepAliveTimeSeconds;
    }

    public void setKeepAliveTimeSeconds(int keepAliveTimeSeconds) {
        if (keepAliveTimeSeconds < KEEP_ALIVE_TIME_SECONDS_MIN) {
            keepAliveTimeSeconds = KEEP_ALIVE_TIME_SECONDS_MIN;
        }
        this.keepAliveTimeSeconds = keepAliveTimeSeconds;
    }

    public int getPacketSizeMax() {
        return packetSizeMax;
    }

    public void setPacketSizeMax(int packetSizeMax) {
        this.packetSizeMax = packetSizeMax;
    }

    public int getReceiveQueueLimit() {
        return receiveQueueLimit;
    }

    public void setReceiveQueueLimit(int receiveQueueLimit) {
        this.receiveQueueLimit = receiveQueueLimit;
    }

    public int getResendMax() {
        return resendMax;
    }

    public void setResendMax(int resendMax) {
        this.resendMax = resendMax;
    }

    public int getSocketTimeoutSeconds() {
        return socketTimeoutSeconds;
    }

    public void setSocketTimeoutSeconds(int socketTimeoutSeconds) {
        this.socketTimeoutSeconds = socketTimeoutSeconds;
    }
}
